package org.beetl.sql.springboot.conf;


import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.beetl.sql.core.ExecuteContext;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.SQLManagerBuilder;
import org.beetl.sql.ext.DBInitHelper;
import org.beetl.sql.ext.spring.SpringConnectionSource;
import org.beetl.sql.starter.SQLManagerCustomize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;


@Configuration
@Slf4j
public class DatasourceConfig {


	@Bean(name = "ds1")
	public DataSource datasource(Environment env) {
		HikariDataSource ds = new HikariDataSource();
		ds.setJdbcUrl(env.getProperty("spring.datasource.url"));
		ds.setUsername(env.getProperty("spring.datasource.username"));
		ds.setPassword(env.getProperty("spring.datasource.password"));
		ds.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
		ds.setMaximumPoolSize(2);
		return ds;
	}

	@Bean(name = "ds2")
	public DataSource datasource2(Environment env) {
		HikariDataSource ds = new HikariDataSource();
		ds.setJdbcUrl(env.getProperty("spring.datasource2.url"));
		ds.setUsername(env.getProperty("spring.datasource2.username"));
		ds.setPassword(env.getProperty("spring.datasource2.password"));
		ds.setDriverClassName(env.getProperty("spring.datasource2.driver-class-name"));
		ds.setMaximumPoolSize(2);
		return ds;
	}

	@Bean(name = "routerDs")
	public DynamicRoutingDataSource routing(@Qualifier("ds1") DataSource ds1,@Qualifier("ds2") DataSource ds2) {
		DynamicRoutingDataSource ds = new DynamicRoutingDataSource();
		ds.setDefaultTargetDataSource(ds1);
		Map<Object,Object> map = new HashMap<>();
		map.put("ds1",ds1);
		map.put("ds2",ds2);
		ds.setTargetDataSources(map);
		return ds;
	}


	/**
	 * 初始化数据库，演示用，实际项目并不需要，实际项目已经为租户创建好数据库或者动态创建数据库。
	 * @return
	 */
	@Bean
	public SQLManagerCustomize mySQLManagerCustomize() {
		return new SQLManagerCustomize() {
			@Override
			public void customize(String sqlMangerName, SQLManager manager) {
				DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource)manager.getDs().getMasterSource();
				dynamicRoutingDataSource.getTargetDataSources().entrySet().forEach(new Consumer<Map.Entry<Object, Object>>() {
					@Override
					public void accept(Map.Entry<Object, Object> objectObjectEntry) {
						DataSource ds = (DataSource) objectObjectEntry.getValue();
						DBInitHelper.executeSqlScript(ds,DatasourceConfig.class.getResourceAsStream("/db/schema.sql"));
					}
				});


			}

			/**
			 * 日志打印用的数据库
			 * @param sqlMangerName
			 * @param builder
			 */
			@Override
			public void customizeBuild(String sqlMangerName, SQLManagerBuilder builder){
				SpringConnectionSource ds = (SpringConnectionSource)builder.getDs();
				TrackedSpringConnectionSource trackedSpringConnectionSource = new TrackedSpringConnectionSource(ds.getMasterSource(),ds.getSlaveSource());
				builder.setDs(trackedSpringConnectionSource);
			}
		};

	}

	public static class TrackedSpringConnectionSource extends SpringConnectionSource {
		public TrackedSpringConnectionSource(DataSource master, DataSource[] slaves) {
			super(master, slaves);

		}
		public Connection getConn(ExecuteContext ctx, boolean isUpdate){
			Connection connection = super.getConn(ctx,isUpdate);
			log.info("use connection "+connection);
			return connection;
		}
	}
}
